//
//  AbilityChanged.m
//  This file is part of D&D Manager
//
//  Created by Matthew Hutton on 25/02/2007.
//
//
//D&D Manager, a D&D Character and battle management program.
//Copyright (C) 2007, Matthew Hutton
//
//This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License along with this program; if not, write to:
//The Free Software Foundation, Inc.,
//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

#import "AbilityChanged.h"
#import "RandomNumbers.h"
#import "limits.h"
#import "SpellMethods.h"

@implementation AbilityChanged
#pragma mark Ability Methods
#pragma mark 

+(void)strengthChangedForChar:(NSManagedObject *)obj{
	//update strength value.
	int strBonus;
	if([obj valueForKey:@"strengthBase"]==nil){
		[obj setValue:nil
			   forKey:@"strength"];
		strBonus=0;
	}else{
		[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"strengthBase"] intValue]+[[obj valueForKey:@"strengthTemp"] intValue]]
			   forKey:@"strength"];
		strBonus=[self scoreToBonus:[obj valueForKey:@"strength"]];
	}
	//do everything else.

	[obj setValue:[NSNumber numberWithInt:(strBonus+[[obj valueForKey:@"baseAttackBonus"] intValue]+[[obj valueForKey:@"meleeMiscBonus"] intValue])]
		   forKey:@"meleeAttackBonus"];
	NSArray *skills;
	skills=[[obj valueForKey:@"skills"] allObjects];
	int i;
	for(i=0;i<[skills count];i++){
		NSManagedObject *skill=[skills objectAtIndex:i];
		if([[skill valueForKey:@"ability"] intValue]==0){//strength
			[skill setValue:[NSNumber numberWithInt:(strBonus+[[skill valueForKey:@"rank"] intValue]+[[skill valueForKey:@"miscBonus"]intValue])]
					 forKey:@"total"];
			[skill setValue:[NSNumber numberWithInt:strBonus]
					 forKey:@"abilityBonus"];
			
		}
	}
}

+(void)dexterityChangedForChar:(NSManagedObject *)obj{
	//update dex value.
	int x;
	if([obj valueForKey:@"dexterityBase"]==nil){
		[obj setValue:nil
			   forKey:@"dexterity"];
		x=0;
	}else{
		[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"dexterityBase"] intValue]+[[obj valueForKey:@"dexterityTemp"] intValue]]
			   forKey:@"dexterity"];
		x=[self scoreToBonus:[obj valueForKey:@"dexterity"]];
	}
	//everything else.
	//reflex stuff.
	int rTot=[[obj valueForKey:@"reflexBase"] intValue]+x+[[obj valueForKey:@"reflexMiscBonus"] intValue];
	[obj setValue:[NSNumber numberWithInt:rTot]
		   forKey:@"reflexTotal"];
	//now do init stuff
	int initTot=x+[[obj valueForKey:@"initiativeMiscBonus"] intValue];
	[obj setValue:[NSNumber numberWithInt:initTot]
		   forKey:@"initiativeBonus"];
	
	//Base Attack Bonus stuff (ranged)
	[obj setValue:[NSNumber numberWithInt:(x+[[obj valueForKey:@"baseAttackBonus"] intValue]+[[obj valueForKey:@"rangedMiscBonus"] intValue])]
		   forKey:@"rangedAttackBonus"];
	//Base Attack Bonus stuff (melee)
	int strBonus=[self scoreToBonus:[obj valueForKey:@"strength"]];
	[obj setValue:[NSNumber numberWithInt:(strBonus+[[obj valueForKey:@"baseAttackBonus"] intValue]+[[obj valueForKey:@"meleeMiscBonus"] intValue])]
		   forKey:@"meleeAttackBonus"];
	//now do AC Stuff.
	int x2=[self dexACBonus:obj];
	//now add up armour class changes.
	int acTot=[[obj valueForKey:@"armourClassArmour"] intValue]+[[obj valueForKey:@"armourClassShield"] intValue]+x2+[[obj valueForKey:@"armourClassDodge"] intValue]+[[obj valueForKey:@"armourClassDeflection"] intValue]+[[obj valueForKey:@"sizeMod"] intValue]+10;
	int acTouchVal=x2+[[obj valueForKey:@"armourClassDodge"] intValue]+[[obj valueForKey:@"armourClassDeflection"] intValue]+[[obj valueForKey:@"sizeMod"] intValue]+10;
	//adding dex penalty to AC flat as required.
	int dexPen=0;
	if(x2<0){
		dexPen=x2;
	}
	int acFlatVal=dexPen+[[obj valueForKey:@"armourClassArmour"] intValue]+[[obj valueForKey:@"armourClassShield"] intValue]+[[obj valueForKey:@"armourClassDeflection"] intValue]+[[obj valueForKey:@"sizeMod"] intValue]+10;
	//check whether default weapon uses a shield or not.
	NSManagedObject *weap=[obj valueForKey:@"defaultWeapon"];
	//now check weapon.
	if([[weap valueForKey:@"withShield"] boolValue]){
		//enable shield for AC bonus.
		[obj setValue:[NSNumber numberWithInt:acTot]
			   forKey:@"armourClassTotal"];
		[obj setValue:[NSNumber numberWithInt:acFlatVal]
			   forKey:@"armourClassFlat"];
	}else{
		//disable shield for AC bonus.
		[obj setValue:[NSNumber numberWithInt:(acTot-[[obj valueForKey:@"armourClassShield"] intValue])]
			   forKey:@"armourClassTotal"];
		[obj setValue:[NSNumber numberWithInt:(acFlatVal-[[obj valueForKey:@"armourClassShield"] intValue])]
			   forKey:@"armourClassFlat"];
	}
	//nothing to do with the shield.
	[obj setValue:[NSNumber numberWithInt:acTouchVal]
		   forKey:@"armourClassTouch"];
	//set up skills
	NSArray *skills;
	skills=[[obj valueForKey:@"skills"] allObjects];
	int i;
	for(i=0;i<[skills count];i++){
		NSManagedObject *skill;
		skill=[skills objectAtIndex:i];
		if([[skill valueForKey:@"ability"] intValue]==2){//dexterity.
			[skill setValue:[NSNumber numberWithInt:(x+[[skill valueForKey:@"rank"] intValue]+[[skill valueForKey:@"miscBonus"]intValue])]
					 forKey:@"total"];
			[skill setValue:[NSNumber numberWithInt:x]
					 forKey:@"abilityBonus"];
		}
	}
}

+(void)constitutionChangedForChar:(NSManagedObject *)obj{
	int conBon;
	//update con value.
	if([obj valueForKey:@"constitutionBase"]==nil){
		[obj setValue:nil
			   forKey:@"constitution"];
		conBon=0;
	}else{
		[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"constitutionBase"] intValue]+[[obj valueForKey:@"constitutionTemp"] intValue]]
			   forKey:@"constitution"];
		conBon=[self scoreToBonus:[obj valueForKey:@"constitution"]];
	}
	//everything else.
	int fTot=[[obj valueForKey:@"fortitudeBase"] intValue]+conBon+[[obj valueForKey:@"fortitudeMiscBonus"] intValue];
	[obj setValue:[NSNumber numberWithInt:fTot]
		   forKey:@"fortitudeTotal"];
	[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"conBonusHP"] intValue]+[[obj valueForKey:@"baseHP"] intValue]]
		   forKey:@"maxHP"];
	//set up skills
	NSArray *skills;
	skills=[[obj valueForKey:@"skills"] allObjects];
	int i;
	for(i=0;i<[skills count];i++){
		NSManagedObject *skill;
		skill=[skills objectAtIndex:i];
		if([[skill valueForKey:@"ability"] intValue]==4){//constitution.
			[skill setValue:[NSNumber numberWithInt:(conBon+[[skill valueForKey:@"rank"] intValue]+[[skill valueForKey:@"miscBonus"]intValue])]
					 forKey:@"total"];
			[skill setValue:[NSNumber numberWithInt:conBon]
					 forKey:@"abilityBonus"];
		}
	}
}
+(void)intelligenceChangedForChar:(NSManagedObject *)obj{
	//update int value.
	int intBonus;
	if([obj valueForKey:@"intelligenceBase"]==nil){
		[obj setValue:nil
			   forKey:@"intelligence"];
		intBonus=0;
	}else{
		[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"intelligenceBase"] intValue]+[[obj valueForKey:@"intelligenceTemp"] intValue]]
			   forKey:@"intelligence"];
		intBonus=[self scoreToBonus:[obj valueForKey:@"intelligence"]];
	}
	//everything else.
	//set up skills
	NSArray *skills=[[obj valueForKey:@"skills"] allObjects];
	int i;
	for(i=0;i<[skills count];i++){
		NSManagedObject *skill;
		skill=[skills objectAtIndex:i];
		if([[skill valueForKey:@"ability"] intValue]==1){//intelligence
			[skill setValue:[NSNumber numberWithInt:intBonus+[[skill valueForKey:@"rank"] intValue]+[[skill valueForKey:@"miscBonus"]intValue]]
					 forKey:@"total"];
			[skill setValue:[NSNumber numberWithInt:intBonus]
					 forKey:@"abilityBonus"];
			
		}
	}
	//now check key ability stuff.
	NSSet *charSpellLevels=[obj valueForKey:@"spellLevel"];
	for(i=1;i<4;i++){
		NSManagedObject *characterClass=[obj valueForKey:[NSString stringWithFormat:@"characterClass%d",i]];
		if(![[characterClass valueForKey:@"keyAttribute"] isEqualToString:@"Intelligence"]){
			continue;
		}
		NSMutableSet *ccSpellLevels=[NSMutableSet setWithCapacity:1];
		[ccSpellLevels setSet:[characterClass valueForKey:@"spellLevel"]];
		[ccSpellLevels intersectSet:charSpellLevels];
		NSArray *array=[ccSpellLevels allObjects];
		int j;
		for(j=0;j<[array count];j++){
			NSManagedObject *spellLevel=[array objectAtIndex:j];
			int abilBon=[self bonusSpellsForCharacter:obj
									forCharacterClass:characterClass
											 forLevel:[[spellLevel valueForKey:@"level"] intValue]];
			[spellLevel setValue:[NSNumber numberWithInt:abilBon]
						  forKey:@"abilityBonusSpells"];
		}
	}
}
+(void)wisdomChangedForChar:(NSManagedObject *)obj{
	//update wis value.
	int x;
	if([obj valueForKey:@"wisdomBase"]==nil){
		[obj setValue:nil
			   forKey:@"wisdom"];
		x=0;
	}else{
		[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"wisdomBase"] intValue]+[[obj valueForKey:@"wisdomTemp"] intValue]]
			   forKey:@"wisdom"];
		x=[self scoreToBonus:[obj valueForKey:@"wisdom"]];
	}
	//everything else.
	int wTot=[[obj valueForKey:@"willBase"] intValue]+x+[[obj valueForKey:@"willMiscBonus"] intValue];
	[obj setValue:[NSNumber numberWithInt:wTot]
		   forKey:@"willTotal"];
	//set up skills
	NSArray *skills=[[obj valueForKey:@"skills"] allObjects];
	int i;
	for(i=0;i<[skills count];i++){
		NSManagedObject *skill;
		skill=[skills objectAtIndex:i];
		if([[skill valueForKey:@"ability"] intValue]==3){//wisdom.
			[skill setValue:[NSNumber numberWithInt:(x+[[skill valueForKey:@"rank"] intValue]+[[skill valueForKey:@"miscBonus"] intValue])]
					 forKey:@"total"];
			[skill setValue:[NSNumber numberWithInt:x]
					 forKey:@"abilityBonus"];
		}
	}
	//now check key ability stuff.
	NSSet *charSpellLevels=[obj valueForKey:@"spellLevel"];
	for(i=1;i<4;i++){
		NSManagedObject *characterClass=[obj valueForKey:[NSString stringWithFormat:@"characterClass%d",i]];
		if(![[characterClass valueForKey:@"keyAttribute"] isEqualToString:@"Wisdom"]){
			continue;
		}
		NSMutableSet *ccSpellLevels=[NSMutableSet setWithCapacity:1];
		[ccSpellLevels setSet:[characterClass valueForKey:@"spellLevel"]];
		[ccSpellLevels intersectSet:charSpellLevels];
		NSArray *array=[ccSpellLevels allObjects];
		int j;
		for(j=0;j<[array count];j++){
			NSManagedObject *spellLevel=[array objectAtIndex:j];
			int abilBon=[self bonusSpellsForCharacter:obj
									forCharacterClass:characterClass
											 forLevel:[[spellLevel valueForKey:@"level"] intValue]];
			[spellLevel setValue:[NSNumber numberWithInt:abilBon]
						  forKey:@"abilityBonusSpells"];
		}
	}
}
+(void)charismaChangedForChar:(NSManagedObject *)obj{
	//update char value.
	//blah blah
	int chaMod;
	if([obj valueForKey:@"charismaBase"]==nil){
		[obj setValue:nil
			   forKey:@"charisma"];
		chaMod=0;
	}else{
		[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"charismaBase"] intValue]+[[obj valueForKey:@"charismaTemp"] intValue]]
			   forKey:@"charisma"];
		chaMod=[self scoreToBonus:[obj valueForKey:@"charisma"]];
	}
	//everything else.
	//turn undead
	[obj setValue:[NSNumber numberWithInt:(3+chaMod+[[obj valueForKey:@"tuMiscBonus"] intValue])]
		   forKey:@"tuTotal"];
	[obj setValue:[NSNumber numberWithInt:(chaMod+[[obj valueForKey:@"tuCMiscBonus"] intValue])]
		   forKey:@"tuCtotal"];
	[obj setValue:[NSNumber numberWithInt:(chaMod+[[obj valueForKey:@"tuHDMiscBonus"] intValue]+[self levelOfTurningForCharacter:obj])]
		   forKey:@"tuHDtotal"];
	//set up skills
	NSArray *skills=[[obj valueForKey:@"skills"] allObjects];
	int i;
	for(i=0;i<[skills count];i++){
		NSManagedObject *skill=[skills objectAtIndex:i];
		if([[skill valueForKey:@"ability"] intValue]==5){//charisma
			[skill setValue:[NSNumber numberWithInt:(chaMod+[[skill valueForKey:@"rank"] intValue]+[[skill valueForKey:@"miscBonus"] intValue])]
					 forKey:@"total"];
			[skill setValue:[NSNumber numberWithInt:chaMod]
					 forKey:@"abilityBonus"];
			
		}
	}
	//now check key ability stuff.
	NSSet *charSpellLevels=[obj valueForKey:@"spellLevel"];
	for(i=1;i<4;i++){
		NSManagedObject *characterClass=[obj valueForKey:[NSString stringWithFormat:@"characterClass%d",i]];
		if(![[characterClass valueForKey:@"keyAttribute"] isEqualToString:@"Charisma"]){
			continue;
		}
		NSMutableSet *ccSpellLevels=[NSMutableSet setWithCapacity:1];
		[ccSpellLevels setSet:[characterClass valueForKey:@"spellLevel"]];
		[ccSpellLevels intersectSet:charSpellLevels];
		NSArray *array=[ccSpellLevels allObjects];
		int j;
		for(j=0;j<[array count];j++){
			NSManagedObject *spellLevel=[array objectAtIndex:j];
			int abilBon=[self bonusSpellsForCharacter:obj
									forCharacterClass:characterClass
											 forLevel:[[spellLevel valueForKey:@"level"] intValue]];
			[spellLevel setValue:[NSNumber numberWithInt:abilBon]
						  forKey:@"abilityBonusSpells"];
		}
	}
}
#pragma mark -
#pragma mark Value Transformers
#pragma mark
+(int)scoreToBonus:(NSNumber *)score{
	if(score==nil){
		return 0;
	}
    int abilityBonus=[score intValue]-10;
	if(abilityBonus<0){
		abilityBonus--;
	}
	return abilityBonus/2;
}
+(int)bonusSpellsForCharacter:(NSManagedObject *)obj
			forCharacterClass:(NSManagedObject *)characterClass
					 forLevel:(int)level{
	NSString *keyAttr=[characterClass valueForKey:@"keyAttribute"];
	if([keyAttr isEqualToString:@""] || keyAttr==nil){
		return 0;
	}
	int keyScore=[[obj valueForKey:[keyAttr lowercaseString]] intValue];
	int testScore=keyScore-(level-1)*2;
	if(testScore<12 || level<1){
		return 0;
	}
	return (testScore-4)/8;
	
}
+(int)dexACBonus:(NSManagedObject*)obj{
	int dexScore=[self scoreToBonus:[obj valueForKey:@"dexterity"]];
	NSString *maxDexBonus=[obj valueForKey:@"maxDexBonus"];
	//NSLog(@"maxDexBonus=%@",maxDexBonus);
	if([maxDexBonus isEqualToString:@"none"]){
		
	}else if ([maxDexBonus isEqualToString:@"+8"]){
		if(dexScore>8){
			dexScore=8;
		}
	}else if ([maxDexBonus isEqualToString:@"+7"]){
		if(dexScore>7){
			dexScore=7;
		}
		
	}else if ([maxDexBonus isEqualToString:@"+6"]){
		if(dexScore>6){
			dexScore=6;
		}
	}else if ([maxDexBonus isEqualToString:@"+5"]){
		if(dexScore>5){
			dexScore=5;
		}
	}else if ([maxDexBonus isEqualToString:@"+4"]){
		if(dexScore>4){
			dexScore=4;
		}
	}else if ([maxDexBonus isEqualToString:@"+3"]){
		if(dexScore>3){
			dexScore=3;
		}
	}else if ([maxDexBonus isEqualToString:@"+2"]){
		if(dexScore>2){
			dexScore=2;
		}
	}else if ([maxDexBonus isEqualToString:@"+1"]){
		if(dexScore>1){
			dexScore=1;
		}
	}else if ([maxDexBonus isEqualToString:@"+0"]){
		if(dexScore>0){
			dexScore=0;
		}
	}
	return dexScore;
}
+(int)abilityAttackBonus:(id)weap{
	NSManagedObject *obj=[weap valueForKey:@"character"];
	int ab;
	if([[weap valueForKey:@"weaponType"] intValue]==2){
		ab=[[obj valueForKey:@"rangedAttackBonus"] intValue];
	}else{
		ab=[[obj valueForKey:@"meleeAttackBonus"] intValue];
	}
	//NSLog(@"1, ab=%d",ab);
	//if a monster secondary attacks have -5 penalty to hit.
	if(![[obj valueForKey:@"usesWeapons"] boolValue] && ![[obj valueForKey:@"defaultWeapon"] isEqualTo:weap]){
		ab=ab-5;
	}
	//NSLog(@"2, ab=%d",ab);
	//if uses two weapons add main/off penalties as required.
	if([[obj valueForKey:@"usesTwoWeapons"] intValue]){
		if([weap isEqualTo:[obj valueForKey:@"defaultWeapon"]]){
			ab=ab+[[obj valueForKey:@"mainHandPenalty"] intValue];
		}else if([weap isEqualTo:[obj valueForKey:@"offWeapon"]]){
			ab=ab+[[obj valueForKey:@"offHandPenalty"] intValue];
		}
	}
	//NSLog(@"3, ab=%d",ab);
	ab=ab+[[obj valueForKey:@"sizeMod"] intValue];
	//NSLog(@"4, ab=%d",ab);
	return ab;
}
+(int)strengthWeaponBonus:(id)weap{
	//first get strength weap from the character.
	NSManagedObject *obj=[weap valueForKey:@"character"];
	int str=[self scoreToBonus:[obj valueForKey:@"strength"]];
	//check if ranged.
	//NSLog(@"1.2");
	if([[weap valueForKey:@"weaponType"] intValue]==2){
		int minStr=[[weap valueForKey:@"minStrengthToUse"] intValue];
		minStr=(minStr-10)/2;
		if(minStr>0){
			if(str>minStr){//min str applies and str is bigger than it.
				str=minStr;
			}
		}else if(str>0){//as strength penalty still applies
			str=0;
		}
	}else{//not ranged
		  //1.5 times str bonus for melee when not using a light weapon two handed or optionally to a monster.
		if(str>0 && ![[weap valueForKey:@"lightWeapon"] boolValue] && [[weap valueForKey:@"weaponType"] intValue]==0 && [[weap valueForKey:@"twoHandedWeapon"] boolValue]){
			str=(str*3 +1)/2;
		}
		//if a monster and the attack is secondary, or weapon is off hand, strength bonus is halved.
		if(str>0 && (![[obj valueForKey:@"usesWeapons"] boolValue] && ![[obj valueForKey:@"defaultWeapon"] isEqualTo:weap]) || [weap isEqualTo:[obj valueForKey:@"offWeapon"]]){
			str=(str+1)/2;
		}
	}
	return str;
}
#pragma mark -
#pragma mark Alignment Checkers
#pragma mark
+(BOOL)isGood:(NSManagedObject *)obj{
	NSString *str=[obj valueForKey:@"alignment"];
	if([str hasSuffix:@"Good"]){
		return YES;
	}
	return NO;
}

+(BOOL)isEvil:(NSManagedObject *)obj{
	NSString *str=[obj valueForKey:@"alignment"];
	if([str hasSuffix:@"Evil"]){
		return YES;
	}
	return NO;
}

+(BOOL)isLawful:(NSManagedObject *)obj{
	NSString *str=[obj valueForKey:@"alignment"];
	if([str hasPrefix:@"Lawful"]){
		return YES;
	}
	return NO;
}

+(BOOL)isChaotic:(NSManagedObject *)obj{
	NSString *str=[obj valueForKey:@"alignment"];
	if([str hasPrefix:@"Chaotic"]){
		return YES;
	}
	return NO;
}
#pragma mark -
#pragma mark Testing Methods
#pragma mark
+(NSString *)runTestSkill:(NSManagedObject *)skill
					forDC:(int)dc{
	int bonus=[[skill valueForKey:@"total"] intValue];
	return [self runTestWithBonus:bonus
							forDC:dc];
}
+(NSString *)runTestWithBonus:(int)bonus
						forDC:(int)dc{
	int dieRoll=[RandomNumbers randomIntUpTo:20];
	if(dieRoll==1){
		//Fails Automatically
		return @"Critical Failure (rolled 1)";
	}else if(dieRoll==20){
		//Succeeds Automatically
		return @"Success (rolled 20)";
	}else{
		if(dieRoll+bonus>=dc){
			//succeeds
			if(bonus>=0){
				return [[NSString alloc] initWithFormat:@"Success (rolled %d+%d)",dieRoll,bonus];
			}else{
				return [[NSString alloc] initWithFormat:@"Success (rolled %d-%d)",dieRoll,-bonus];
			}
		}else{
			//fails
			if(bonus>=0){
				return [[NSString alloc] initWithFormat:@"Failed (rolled %d+%d)",dieRoll,bonus];
			}else{
				return [[NSString alloc] initWithFormat:@"Failed (rolled %d-%d)",dieRoll,-bonus];
			}
		}
	}
	
}
#pragma mark -
#pragma mark Gender methods
#pragma mark
+(NSString *)getGenderOfCharacter:(NSManagedObject *)obj{
	if([[obj valueForKey:@"gender"] intValue]==0){
		return @"he";
	}else if([[obj valueForKey:@"gender"] intValue]==1){
		return @"she";
	}else{
		return @"it";
	}
}
+(NSString *)getTPSGenderOfCharacter:(NSManagedObject *)obj{
	if([[obj valueForKey:@"gender"] intValue]==0){
		return @"him";
	}else if([[obj valueForKey:@"gender"] intValue]==1){
		return @"her";
	}else{
		return @"it";
	}
}

+(NSString *)getAdjGenderOfCharacter:(NSManagedObject *)obj{
	if([[obj valueForKey:@"gender"] intValue]==0){
		return @"his";
	}else if([[obj valueForKey:@"gender"] intValue]==1){
		return @"her";
	}else{
		return @"their";
	}
}
#pragma mark -
#pragma mark Weapons
#pragma mark

+(NSString *)updateDefaultWeaponForChar:(NSManagedObject *)obj{
	NSArray *array=[[obj valueForKey:@"weapons"] allObjects];
	if([array count]==0){//no objects in array.
		return @"";
	}
	NSManagedObject *weap=[obj valueForKey:@"defaultWeapon"];
	//check if new weapon is two handed/ranged. (off weapon)
	if([[weap valueForKey:@"twoHandedWeapon"] boolValue] || [[weap valueForKey:@"weaponType"] intValue]!=0){
		[obj setValue:[NSNumber numberWithBool:NO]
			   forKey:@"usesTwoWeapons"];
		[obj setValue:nil
			   forKey:@"offWeapon"];
	}
	NSString *defName=[weap valueForKey:@"name"];
	//now check if uses two weapons so name needs to include this weapon.
	if([[obj valueForKey:@"usesTwoWeapons"] boolValue]){
		defName=[[NSString alloc] initWithFormat:@"%@ + %@",defName,[[obj valueForKey:@"offWeapon"] valueForKey:@"name"]];
		[weap setValue:[NSNumber numberWithBool:NO]
				forKey:@"withShield"];
	}
	[self updateShieldBonusForChar:obj
						 forWeapon:weap];
	[obj setValue:defName
		   forKey:@"defaultWeaponForDisp"];
	return defName;
}

+(void)updateShieldBonusForChar:(NSManagedObject *)obj
					  forWeapon:(NSManagedObject *)weap{
	int x=[self dexACBonus:obj];//dex bonus.
	int acShield=[[obj valueForKey:@"armourClassShield"] intValue];
	int acTot=[[obj valueForKey:@"armourClassArmour"] intValue]+acShield+x+[[obj valueForKey:@"armourClassDodge"] intValue]+[[obj valueForKey:@"armourClassDeflection"] intValue]+[[obj valueForKey:@"sizeMod"] intValue]+10;
	int acFlatVal=[[obj valueForKey:@"armourClassArmour"] intValue]+acShield+[[obj valueForKey:@"armourClassDeflection"] intValue]+[[obj valueForKey:@"sizeMod"] intValue]+10;
	if([[weap valueForKey:@"withShield"] boolValue]){
		//enable shield for AC bonus.
		[obj setValue:[NSNumber numberWithInt:acTot]
			   forKey:@"armourClassTotal"];
		[obj setValue:[NSNumber numberWithInt:acFlatVal]
			   forKey:@"armourClassFlat"];
	}else{
		//disable shield for AC bonus.
		[obj setValue:[NSNumber numberWithInt:(acTot-acShield)]
			   forKey:@"armourClassTotal"];
		[obj setValue:[NSNumber numberWithInt:(acFlatVal-acShield)]
			   forKey:@"armourClassFlat"];
	}		
}

+(void)setDefaultWeaponForChar:(NSManagedObject *)obj
					withWeapon:(NSManagedObject *)newWeap{
	NSManagedObject *oldWeap=[obj valueForKey:@"defaultWeapon"];
	[obj setValue:newWeap
		   forKey:@"defaultWeapon"];
	//check if both weapons are the same or the new weapon cannot be used with a second weapon and then switch of two weapon mode.
	if([[obj valueForKey:@"usesTwoWeapons"] boolValue] && ([newWeap isEqualTo:[obj valueForKey:@"offWeapon"]] || [[newWeap valueForKey:@"twoHandedWeapon"] boolValue] || [[newWeap valueForKey:@"weaponType"] intValue]==2)){
		//if light then reduce off weapon penalty as required.
		NSManagedObject *offWeap=[obj valueForKey:@"offWeapon"];
		if([[offWeap valueForKey:@"lightWeapon"] boolValue]){
			[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"offHandPenalty"] intValue]-2)]
				   forKey:@"offHandPenalty"];
			[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"mainHandPenalty"] intValue]-2)]
				   forKey:@"mainHandPenalty"];
		}
		[offWeap setValue:[NSNumber numberWithBool:NO]
				   forKey:@"offWeapon"];
		[obj setValue:nil
			   forKey:@"offWeapon"];
		[obj setValue:[NSNumber numberWithBool:NO]
			   forKey:@"usesTwoWeapons"];
	}
	[oldWeap setValue:nil
			   forKey:@"characterMW"];
	[oldWeap setValue:[NSNumber numberWithBool:NO]
			   forKey:@"defaultWeapon"];
	[newWeap setValue:[NSNumber numberWithBool:YES]
			   forKey:@"defaultWeapon"];
	//updating weapon stats.
	[newWeap setValue:[NSNumber numberWithInt:[[newWeap valueForKey:@"weaponAttackBonus"] intValue]+[self abilityAttackBonus:newWeap]]
			   forKey:@"attackBonus"];		
	//check shield ac bonus.
	[self updateDefaultWeaponForChar:obj];
}
+(void)setOffHandWeaponForChar:(NSManagedObject *)obj
					withWeapon:(NSManagedObject *)newWeap{
	//check compatability first.
	NSManagedObject *defaultWeapon=[obj valueForKey:@"defaultWeapon"];
	if(defaultWeapon==nil){
		//no default weapon.
		[self setDefaultWeaponForChar:obj
						   withWeapon:newWeap];
		return;
	}
	if([[defaultWeapon valueForKey:@"type"] intValue]==2 || [[defaultWeapon valueForKey:@"twoHandedWeapon"] boolValue] || ![[obj valueForKey:@"usesWeapons"] boolValue]){
		return;
	}
	NSManagedObject *oldWeap=[obj valueForKey:@"offWeapon"];
	[obj setValue:newWeap
		   forKey:@"offWeapon"];
	[obj setValue:[NSNumber numberWithBool:YES]
		   forKey:@"usesTwoWeapons"];
	[oldWeap setValue:nil
			   forKey:@"characterOW"];
	[oldWeap setValue:[NSNumber numberWithBool:NO]
			   forKey:@"offWeapon"];
	[newWeap setValue:[NSNumber numberWithBool:YES]
			   forKey:@"offWeapon"];
	[newWeap setValue:[NSNumber numberWithBool:NO]
			   forKey:@"withShield"];
	//check if light weapon, if so, TWOffWeapon gets a +2 bouns.
	if([[newWeap valueForKey:@"lightWeapon"] boolValue] && ![[oldWeap valueForKey:@"lightWeapon"] boolValue]){
		[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"offHandPenalty"] intValue]+2)]
			   forKey:@"offHandPenalty"];
		[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"mainHandPenalty"] intValue]+2)]
			   forKey:@"mainHandPenalty"];
	}
	if(![[newWeap valueForKey:@"lightWeapon"] boolValue] && [[oldWeap valueForKey:@"lightWeapon"] boolValue]){
		[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"offHandPenalty"] intValue]-2)]
			   forKey:@"offHandPenalty"];
		[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"mainHandPenalty"] intValue]-2)]
			   forKey:@"mainHandPenalty"];
	}
	//check shield ac bonus.
	[self updateDefaultWeaponForChar:obj];
}
+(void)cancelOffHandWeaponForChar:(NSManagedObject *)obj{
	NSManagedObject *oldWeap=[obj valueForKey:@"offWeapon"];
	[obj setValue:nil
		   forKey:@"offWeapon"];
	[oldWeap setValue:[NSNumber numberWithBool:NO]
			   forKey:@"offWeapon"];
	[obj setValue:[NSNumber numberWithBool:NO]
		   forKey:@"usesTwoWeapons"];
	//remove light bonus.
	if([[oldWeap valueForKey:@"lightWeapon"] boolValue] && oldWeap!=nil){
		[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"mainHandPenalty"] intValue]-2)]
			   forKey:@"mainHandPenalty"];
		[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"offHandPenalty"] intValue]-2)]
			   forKey:@"offHandPenalty"];
	}
	
	//check shield ac bonus.
	[self updateDefaultWeaponForChar:obj];
}
#pragma mark -
#pragma mark Random
#pragma mark

+(void)setLevelOrXPForChar:(NSManagedObject *)obj
		 forCharacterClass:(NSManagedObject *)characterClass
		 bonusLimitedToL20:(BOOL)limited{
	int lvl=[[obj valueForKey:@"charClassLvl1"] intValue]+[[obj valueForKey:@"charClassLvl2"] intValue]+[[obj valueForKey:@"charClassLvl3"] intValue]+[[obj valueForKey:@"charClassLvlMod"] intValue];	
	int xpForNext=0;
	int i;
	for(i=1;i<=lvl;i++){
		xpForNext=xpForNext+i*1000;
	}
	//now check level isn't too high.
	int cxp=[[obj valueForKey:@"xp"] intValue];
	int lvlFromXp=0;
	while(cxp>-1){
		lvlFromXp++;
		cxp=cxp-lvlFromXp*1000;
	}
	BOOL xpTooLow=NO;
	if(lvlFromXp<lvl){//then the level is too high
		xpTooLow=YES;
	}
	BOOL xpTooHigh=NO;
	if(lvlFromXp>lvl){//a level up is needed.
		xpTooHigh=YES;
	}
	[obj setValue:[NSNumber numberWithInt:lvl]
		   forKey:@"level"];
	[obj setValue:[NSNumber numberWithInt:xpForNext]
		   forKey:@"xpToNextLevel"];
	[obj setValue:[NSNumber numberWithBool:xpTooLow]
		   forKey:@"xpTooLow"];
	[obj setValue:[NSNumber numberWithBool:xpTooHigh]
		   forKey:@"xpTooHigh"];
	int clericLevel=[AbilityChanged levelOfTurningForCharacter:obj];
	[obj setValue:[NSNumber numberWithInt:clericLevel]
		   forKey:@"clericLevel"];
	[obj setValue:[NSNumber numberWithInt:([self scoreToBonus:[obj valueForKey:@"charisma"]]+[[obj valueForKey:@"tuHDMiscBonus"] intValue]+clericLevel)]
		   forKey:@"tuHDtotal"];
	[self setupBaseAttackEtcForCharacter:obj
					   bonusLimitedToL20:limited];
	if(characterClass!=nil){
		NSArray *spellLevels=[[[obj valueForKey:@"spellLevel"] allObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"characterClass.name LIKE[c] \"%@\"",[characterClass valueForKey:@"name"]]]];
		int casterLevel=-1;
		if([[obj valueForKey:@"characterClass1"] isEqualTo:characterClass]){
			casterLevel=[[obj valueForKey:@"charClassLvl1"] intValue];
		}else if([[obj valueForKey:@"characterClass2"] isEqualTo:characterClass]){
			casterLevel=[[obj valueForKey:@"charClassLvl2"] intValue];		
		}else if([[obj valueForKey:@"characterClass3"] isEqualTo:characterClass]){
			casterLevel=[[obj valueForKey:@"charClassLvl3"] intValue];
		}		
		for(i=0;i<[spellLevels count];i++){
			[SpellMethods setupBaseAvailableSpellsForCC:characterClass
										  forSpellLevel:[spellLevels objectAtIndex:i]
										  atCasterLevel:casterLevel];
		}	
	}
	[self getNumberOfFeatsForTheCharacter:obj];
}

+(NSManagedObject *)findTheCharacterWithMostHPLostInTheArray:(NSArray *)arrayOfChars{
	int difference=0;
	NSManagedObject *objToReturn;
	int i;
	for(i=0;i<[arrayOfChars count];i++){
		NSManagedObject *obj=[arrayOfChars objectAtIndex:i];
		if(i==0){
			objToReturn=obj;
			difference==[[obj valueForKey:@"maxHP"] intValue]-[[obj valueForKey:@"currentHP"] intValue];
			continue;
		}
		int newDiff=[[obj valueForKey:@"maxHP"] intValue]-[[obj valueForKey:@"currentHP"] intValue];
		if(newDiff>difference){
			objToReturn=obj;
			difference=newDiff;
		}
	}
	return objToReturn;
}

+(void)setupBaseAttackEtcForCharacter:(NSManagedObject *)obj
					bonusLimitedToL20:(BOOL)limited{
	if(![[obj valueForKey:@"classControlsBaseAttackAndSaves"] boolValue]){
		return;
	}
	int i;
	int fortFigure=0;
	int reflexFigure=0;
	int willFigure=0;
	int baseAttack=0;
	for(i=1;i<4;i++){
		NSManagedObject *characterClass=[obj valueForKey:[NSString stringWithFormat:@"characterClass%d",i]];
		int level=[[obj valueForKey:[NSString stringWithFormat:@"charClassLvl%d",i]] intValue];
		if(level>20 && limited){
			level=20;
		}
		if(characterClass==nil || level==0){
			continue;
		}
		if([[characterClass valueForKey:@"fortitudeMajor"] boolValue]){
			fortFigure=fortFigure+(int)(level/2)+2;
		}else{
			fortFigure=fortFigure+(int)(level/3);
		}
		if([[characterClass valueForKey:@"reflexMajor"] boolValue]){
			reflexFigure=reflexFigure+(int)(level/2)+2;
		}else{
			reflexFigure=reflexFigure+(int)(level/3);
		}
		if([[characterClass valueForKey:@"willMajor"] boolValue]){
			willFigure=willFigure+(int)(level/2)+2;
		}else{
			willFigure=willFigure+(int)(level/3);
		}
		if([[characterClass valueForKey:@"baseAttackType"] intValue]==0){
			baseAttack=baseAttack+level;
		}else if([[characterClass valueForKey:@"baseAttackType"] intValue]==1){
			baseAttack=baseAttack+(int)((level*3)/4);
		}else if([[characterClass valueForKey:@"baseAttackType"] intValue]==2){
			baseAttack=baseAttack+(int)(level/2);
		}
	}
	[obj setValue:[NSNumber numberWithInt:fortFigure]
		   forKey:@"fortitudeBase"];
	[obj setValue:[NSNumber numberWithInt:reflexFigure]
		   forKey:@"reflexBase"];
	[obj setValue:[NSNumber numberWithInt:willFigure]
		   forKey:@"willBase"];
	[obj setValue:[NSNumber numberWithInt:baseAttack]
		   forKey:@"baseAttackBonus"];
	[AbilityChanged dexterityChangedForChar:obj];
	[AbilityChanged wisdomChangedForChar:obj];
	[AbilityChanged constitutionChangedForChar:obj];
}
+(void)getNumberOfFeatsForTheCharacter:(NSManagedObject *)obj{
	int i;
	int baseFeats=0;
	int bonusFeats=0;
	for(i=1;i<4;i++){
		NSManagedObject *characterClass=[obj valueForKey:[NSString stringWithFormat:@"characterClass%d",i]];
		int level=[[obj valueForKey:[NSString stringWithFormat:@"charClassLvl%d",i]] intValue];
		//get base number first.
		double baseNo=[[NSUserDefaults standardUserDefaults] floatForKey:@"levelsPerNewFeat"];
		if(baseNo!=0.0){
			baseFeats=baseFeats+(int)(level/baseNo);
		}
		//get bonus number
		if([[characterClass valueForKey:@"bonusFeatAtLevel1"] boolValue]){
			bonusFeats++;
		}
		if([[characterClass valueForKey:@"levelsPerBonusFeat"] intValue]>0){
			int effectiveLevel=level;
			if([[characterClass valueForKey:@"maxLevelOfBonusFeats"] intValue]>0){
				int maxLevel=[[characterClass valueForKey:@"maxLevelOfBonusFeats"] intValue];
				if(effectiveLevel>maxLevel){
					effectiveLevel=maxLevel;
				}
			}
			int baseNo=[[characterClass valueForKey:@"levelsPerBonusFeat"] intValue];
			bonusFeats=bonusFeats+(int)(effectiveLevel/baseNo);
		}
	}
	[obj setValue:[NSNumber numberWithInt:bonusFeats]
		   forKey:@"noOfBonusFeats"];
	[obj setValue:[NSNumber numberWithInt:baseFeats]
		   forKey:@"noOfBaseFeats"];
	[obj setValue:[NSNumber numberWithInt:baseFeats+[[obj valueForKey:@"noOfMiscFeats"] intValue]+bonusFeats]
		   forKey:@"noOfTotalFeats"];
}
+(int)conHPBonusForCharacter:(NSManagedObject *)obj
		   bonusLimitedToL20:(BOOL)limited{
	int conBonus=[AbilityChanged scoreToBonus:[obj valueForKey:@"constitution"]];
	//multiply by level
	int level=[[obj valueForKey:@"charClassLvl1"] intValue]+[[obj valueForKey:@"charClassLvl2"] intValue]+[[obj valueForKey:@"charClassLvl3"] intValue]+[[obj valueForKey:@"charClassLvlMod"] intValue];
	if(limited && level>20){
		level=20;
	}
	return conBonus*level;	
}
+(void)setupGlobalSpellLevelsForCharacterClass:(NSManagedObject *)characterClass{
	NSManagedObjectContext *mObjC=[characterClass managedObjectContext];
	NSMutableArray *gsl=[NSMutableArray arrayWithCapacity:1];
	[gsl setArray:[[characterClass valueForKey:@"globalSpellLevel"] allObjects]];
	[gsl sortUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"level" ascending:YES]]];
	int newMinValue=[[characterClass valueForKey:@"minimumSpellLevel"] intValue];
	int newMaxValue=[[characterClass valueForKey:@"maximumSpellLevel"] intValue];
	int oldMinValue=0;
	int oldMaxValue=0;
	if(newMaxValue==oldMaxValue && oldMinValue==newMinValue){
		return;
	}
	//NSLog(@"gsl.count=%d",[[globalSpellLevelController arrangedObjects] count]);
	if([gsl count]>0){
		oldMinValue=[[[gsl objectAtIndex:0] valueForKey:@"level"] intValue];
		oldMaxValue=[[[gsl objectAtIndex:[gsl count]-1] valueForKey:@"level"] intValue];
		if(oldMinValue<newMinValue){
			int i;
			for(i=0;i<newMinValue-oldMinValue;i++){
				NSManagedObject *theGsl=[gsl objectAtIndex:0];
				[gsl removeObject:theGsl];
				[mObjC deleteObject:theGsl];
			}
		}
		if(oldMaxValue>newMaxValue){
			int i;
			for(i=0;i<oldMaxValue-newMaxValue;i++){
				NSManagedObject *theGsl=[gsl objectAtIndex:[gsl count]-1];
				[gsl removeObject:theGsl];
				[mObjC deleteObject:theGsl];
			}
		}
		if(newMinValue<oldMinValue){
			int i;
			for(i=0;i<oldMinValue-newMinValue;i++){
				NSLog(@"min");
				NSManagedObject *newGsl=[[NSManagedObject alloc] initWithEntity:[NSEntityDescription entityForName:@"GlobalSpellLevel" inManagedObjectContext:mObjC] insertIntoManagedObjectContext:mObjC];
				[newGsl setValue:characterClass
						  forKey:@"characterClass"];
				[newGsl setValue:[NSNumber numberWithInt:i+newMinValue]
						  forKey:@"level"];
				[self setupStandardGlobalSpellLevelsForCharacterClass:characterClass
															   forGSL:newGsl];
				//[globalSpellLevelController addObject:newGsl];
			}
		}
		if(newMaxValue>oldMaxValue){
			int i;
			for(i=0;i<newMaxValue-oldMaxValue;i++){
				NSLog(@"max");
				NSManagedObject *newGsl=[[NSManagedObject alloc] initWithEntity:[NSEntityDescription entityForName:@"GlobalSpellLevel" inManagedObjectContext:mObjC] insertIntoManagedObjectContext:mObjC];
				[newGsl setValue:characterClass
						  forKey:@"characterClass"];
				[newGsl setValue:[NSNumber numberWithInt:i+oldMaxValue+1]
						  forKey:@"level"];
				[self setupStandardGlobalSpellLevelsForCharacterClass:characterClass
															   forGSL:newGsl];
				//[globalSpellLevelController addObject:newGsl];
			}
		}
		
	}else{
		int i;
		for(i=0;i<=newMaxValue-newMinValue;i++){
			//NSLog(@"norm");
			NSManagedObject *newGsl=[[NSManagedObject alloc] initWithEntity:[NSEntityDescription entityForName:@"GlobalSpellLevel" inManagedObjectContext:mObjC] insertIntoManagedObjectContext:mObjC];
			[newGsl setValue:characterClass
					  forKey:@"characterClass"];
			[newGsl setValue:[NSNumber numberWithInt:i+newMinValue]
					  forKey:@"level"];
			[self setupStandardGlobalSpellLevelsForCharacterClass:characterClass
														   forGSL:newGsl];
			//[globalSpellLevelController addObject:newGsl];
		}
	}
}
+(void)setupStandardGlobalSpellLevelsForCharacterClass:(NSManagedObject *)characterClass
												forGSL:(NSManagedObject *)globalSpellLevel{
	int level=[[globalSpellLevel valueForKey:@"level"] intValue];
	if([[characterClass valueForKey:@"name"] isEqualToString:@"Bard"]){
		if(level==0){
			[globalSpellLevel setValue:[NSNumber numberWithInt:1]
								forKey:@"spd2"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:2]
								forKey:@"spd3"];
		}else if(level==1){
			[globalSpellLevel setValue:[NSNumber numberWithInt:2]
								forKey:@"spd0"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:3]
								forKey:@"spd1"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:4]
								forKey:@"spd2"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:5]
								forKey:@"spd3"];
		}else if(level==6){
			[globalSpellLevel setValue:[NSNumber numberWithInt:16]
								forKey:@"spd0"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:17]
								forKey:@"spd1"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:18]
								forKey:@"spd2"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:19]
								forKey:@"spd3"];
		}else{
			[globalSpellLevel setValue:[NSNumber numberWithInt:level*3-2]
								forKey:@"spd0"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:level*3-1]
								forKey:@"spd1"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:level*3]
								forKey:@"spd2"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:level*3+2]
								forKey:@"spd3"];
		}
		[globalSpellLevel setValue:[NSNumber numberWithInt:14+level]
							forKey:@"spd4"];
		//now doing total spells.
		if(level==0){
			[globalSpellLevel setValue:[NSNumber numberWithInt:1]
								forKey:@"ts4"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:2]
								forKey:@"ts5"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:3]
								forKey:@"ts6"];
		}else{
			int startVal=level*3;
			if(level==1){
				startVal++;
			}
			[globalSpellLevel setValue:[NSNumber numberWithInt:startVal-2]
								forKey:@"ts2"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:startVal-1]
								forKey:@"ts3"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:startVal+1]
								forKey:@"ts4"];
			if(level!=6){
				[globalSpellLevel setValue:[NSNumber numberWithInt:level+15]
									forKey:@"ts5"];
			}
		}
	}else if([[characterClass valueForKey:@"name"] isEqualToString:@"Cleric"] || [[characterClass valueForKey:@"name"] isEqualToString:@"Druid"]){
		if(level==0){
			[globalSpellLevel setValue:[NSNumber numberWithInt:1]
								forKey:@"spd3"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:2]
								forKey:@"spd4"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:4]
								forKey:@"spd5"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:7]
								forKey:@"spd6"];
		}else{
			[globalSpellLevel setValue:[NSNumber numberWithInt:level*2-1]
								forKey:@"spd1"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:level*2]
								forKey:@"spd2"];
			if(level==9){
				[globalSpellLevel setValue:[NSNumber numberWithInt:19]
									forKey:@"spd3"];
				[globalSpellLevel setValue:[NSNumber numberWithInt:20]
									forKey:@"spd4"];
			}else{
				[globalSpellLevel setValue:[NSNumber numberWithInt:level*2+2]
									forKey:@"spd3"];
				if(level==8){
					[globalSpellLevel setValue:[NSNumber numberWithInt:20]
										forKey:@"spd4"];
				}else{
					[globalSpellLevel setValue:[NSNumber numberWithInt:level*2+5]
										forKey:@"spd4"];
					if(level<6){
						[globalSpellLevel setValue:[NSNumber numberWithInt:level*2+9]
											forKey:@"spd5"];
					}
				}
			}
		}
	}else if([[characterClass valueForKey:@"name"] isEqualToString:@"Paladin"] || [[characterClass valueForKey:@"name"] isEqualToString:@"Ranger"]){
		if(level==1){
			[globalSpellLevel setValue:[NSNumber numberWithInt:4]
								forKey:@"spd0"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:6]
								forKey:@"spd1"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:14]
								forKey:@"spd2"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:18]
								forKey:@"spd3"];
		}else if(level==2){
			[globalSpellLevel setValue:[NSNumber numberWithInt:8]
								forKey:@"spd0"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:10]
								forKey:@"spd1"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:16]
								forKey:@"spd2"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:19]
								forKey:@"spd3"];
		}else if(level==3){
			[globalSpellLevel setValue:[NSNumber numberWithInt:11]
								forKey:@"spd0"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:12]
								forKey:@"spd1"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:17]
								forKey:@"spd2"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:19]
								forKey:@"spd3"];
		}else if(level==4){
			[globalSpellLevel setValue:[NSNumber numberWithInt:14]
								forKey:@"spd0"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:15]
								forKey:@"spd1"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:19]
								forKey:@"spd2"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:20]
								forKey:@"spd3"];
		}
	}else if([[characterClass valueForKey:@"name"] isEqualToString:@"Sorcerer"]){
		if(level==0){
			[globalSpellLevel setValue:[NSNumber numberWithInt:1]
								forKey:@"spd5"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:2]
								forKey:@"spd6"];
		}else if(level==9){
			[globalSpellLevel setValue:[NSNumber numberWithInt:18]
								forKey:@"spd3"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:19]
								forKey:@"spd4"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:20]
								forKey:@"spd6"];
		}else{
			int startVal=level*2;
			if(level==1){
				startVal--;
			}
			[globalSpellLevel setValue:[NSNumber numberWithInt:startVal]
								forKey:@"spd3"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:startVal+1]
								forKey:@"spd4"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:startVal+2]
								forKey:@"spd5"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:startVal+3]
								forKey:@"spd6"];
		}
		//now total spells
		if(level==0){
			[globalSpellLevel setValue:[NSNumber numberWithInt:1]
								forKey:@"ts4"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:2]
								forKey:@"ts5"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:4]
								forKey:@"ts6"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:6]
								forKey:@"ts7"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:8]
								forKey:@"ts8"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:10]
								forKey:@"ts9"];
		}else if(level==1){
			[globalSpellLevel setValue:[NSNumber numberWithInt:1]
								forKey:@"ts2"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:3]
								forKey:@"ts3"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:5]
								forKey:@"ts4"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:7]
								forKey:@"ts5"];
		}else if(level<9){
			[globalSpellLevel setValue:[NSNumber numberWithInt:level*2]
								forKey:@"ts1"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:level*2+1]
								forKey:@"ts2"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:level*2+3]
								forKey:@"ts3"];
			if(level<6){
				[globalSpellLevel setValue:[NSNumber numberWithInt:level*2+5]
									forKey:@"ts4"];
			}
			if(level==2){
				[globalSpellLevel setValue:[NSNumber numberWithInt:11]
									forKey:@"ts5"];
			}
		}else if(level==9){
			[globalSpellLevel setValue:[NSNumber numberWithInt:18]
								forKey:@"ts1"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:19]
								forKey:@"ts2"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:20]
								forKey:@"ts3"];
		}
	}else if([[characterClass valueForKey:@"name"] isEqualToString:@"Wizard"]){
		if(level==0){
			[globalSpellLevel setValue:[NSNumber numberWithInt:1]
								forKey:@"spd3"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:2]
								forKey:@"spd4"];
		}else{
			[globalSpellLevel setValue:[NSNumber numberWithInt:level*2-1]
								forKey:@"spd1"];
			[globalSpellLevel setValue:[NSNumber numberWithInt:level*2]
								forKey:@"spd2"];
			if(level==9){
				[globalSpellLevel setValue:[NSNumber numberWithInt:19]
									forKey:@"spd3"];
				[globalSpellLevel setValue:[NSNumber numberWithInt:20]
									forKey:@"spd4"];
			}else{
				[globalSpellLevel setValue:[NSNumber numberWithInt:level*2+2]
									forKey:@"spd3"];
				if(level==8){
					[globalSpellLevel setValue:[NSNumber numberWithInt:20]
										forKey:@"spd4"];
				}else{
					[globalSpellLevel setValue:[NSNumber numberWithInt:level*2+5]
										forKey:@"spd4"];
				}
			}
		}
	}	
}
#pragma mark -
#pragma mark Skills
#pragma mark 
+(void)setupSkillAbilityBonusForSkill:(NSManagedObject *)skill{
	 [self setupSkillAbilityBonusForSkill:skill
							 forCharacter:[skill valueForKey:@"character"]];
}
+(void)setupSkillAbilityBonusForSkill:(NSManagedObject *)skill
						 forCharacter:(NSManagedObject *)obj{
	if(![[[skill valueForKey:@"superskill"] valueForKey:@"hasKeyAbility"] boolValue]){
		[skill setValue:[NSNumber numberWithInt:0]
				 forKey:@"abilityBonus"];
	}else{
		int abilNo=[[skill valueForKey:@"ability"] intValue];
		if(abilNo==0){
			[skill setValue:[NSNumber numberWithInt:[self scoreToBonus:[obj valueForKey:@"strength"]]]
					 forKey:@"abilityBonus"];
		}else if(abilNo==2){
			[skill setValue:[NSNumber numberWithInt:[self scoreToBonus:[obj valueForKey:@"dexterity"]]]
					 forKey:@"abilityBonus"];
		}else if(abilNo==4){
			[skill setValue:[NSNumber numberWithInt:[self scoreToBonus:[obj valueForKey:@"constitution"]]]
					 forKey:@"abilityBonus"];
		}else if(abilNo==1){ 
			[skill setValue:[NSNumber numberWithInt:[self scoreToBonus:[obj valueForKey:@"intelligence"]]]
					 forKey:@"abilityBonus"];
		}else if(abilNo==3){
			[skill setValue:[NSNumber numberWithInt:[self scoreToBonus:[obj valueForKey:@"wisdom"]]]
					 forKey:@"abilityBonus"];
		}else if(abilNo==5){
			[skill setValue:[NSNumber numberWithInt:[self scoreToBonus:[obj valueForKey:@"charisma"]]]
					 forKey:@"abilityBonus"];
		}		
	}
	[skill setValue:[NSNumber numberWithInt:[[skill valueForKey:@"rank"] intValue]+[[skill valueForKey:@"miscBonus"] intValue]+[[skill valueForKey:@"abilityBonus"] intValue]]
			 forKey:@"total"];
}

+(void)processArmourCheckPenaltyForSkill:(NSManagedObject *)skill
							forCharacter:(NSManagedObject *)obj
								   wasOn:(BOOL)wasOn
									isOn:(BOOL)isOn{
	if((wasOn && isOn) || (!wasOn && !isOn)){
		//no change.
		return;
	}
	if(!wasOn && isOn){
		[skill setValue:[NSNumber numberWithInt:([[skill valueForKey:@"miscBonus"] intValue]+[[obj valueForKey:@"armourCheckPenalty"] intValue])]
				 forKey:@"miscBonus"];
		[skill setValue:[NSNumber numberWithInt:([[skill valueForKey:@"total"] intValue]+[[obj valueForKey:@"armourCheckPenalty"] intValue])]
				 forKey:@"total"];
		[skill setValue:[NSNumber numberWithBool:YES]
				 forKey:@"armourCheckApplies"];
	}else if(wasOn && !isOn){
		[skill setValue:[NSNumber numberWithInt:([[skill valueForKey:@"miscBonus"] intValue]-[[obj valueForKey:@"armourCheckPenalty"] intValue])]
				 forKey:@"miscBonus"];
		[skill setValue:[NSNumber numberWithInt:([[skill valueForKey:@"total"] intValue]-[[obj valueForKey:@"armourCheckPenalty"] intValue])]
				 forKey:@"total"];
		[skill setValue:[NSNumber numberWithBool:NO]
				 forKey:@"armourCheckApplies"];
	}
}
+(NSManagedObject *)createAndSetupSkillFromSuperskill:(NSManagedObject *)superskill
										 forCharacter:(NSManagedObject *)obj{
	NSManagedObjectContext *mObjC=[obj managedObjectContext];
	NSManagedObjectModel *model=[[mObjC persistentStoreCoordinator] managedObjectModel];
	NSManagedObject *skill=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"Skill"]
									insertIntoManagedObjectContext:mObjC];
	[skill setValue:obj
			 forKey:@"character"];
	[skill setValue:superskill
			 forKey:@"superskill"];
	NSString *name=[superskill valueForKey:@"name"];
	if([[superskill valueForKey:@"multipleSubskills"] boolValue]){
		NSArray *array=[[[obj valueForKey:@"skills"] allObjects] valueForKey:@"name"];
		if([array containsObject:name]){
			BOOL goOn=NO;
			int j=2;
			while(!goOn){
				if([array containsObject:[NSString stringWithFormat:@"%@ #%d",name,j]]){
					j++;
				}else{
					name=[NSString stringWithFormat:@"%@ #%d",name,j];
					goOn=YES;
					break;
				}
			}
		}
	}
	[skill setValue:name
			 forKey:@"name"];
	[skill setValue:[superskill valueForKey:@"ability"]
			 forKey:@"ability"];
	[self setupSkillAbilityBonusForSkill:skill
							forCharacter:obj];
	[self processArmourCheckPenaltyForSkill:skill
							   forCharacter:obj
									  wasOn:NO
									   isOn:[[superskill valueForKey:@"armourCheckApplies"] boolValue]];
	[skill setValue:[superskill valueForKey:@"armourCheckApplies"]
			 forKey:@"armourCheckApplies"];
	if(![[superskill valueForKey:@"useUntrained"] boolValue]){
		[skill setValue:[NSNumber numberWithInt:1]
				 forKey:@"rank"];
	}
	//check if name can be edited.
	if([[superskill valueForKey:@"multipleSubskills"] boolValue]){
		[skill setValue:[NSNumber numberWithBool:YES]
				 forKey:@"nameEditable"];
	}else{
		[skill setValue:[NSNumber numberWithBool:NO]
				 forKey:@"nameEditable"];
	}
	return skill;
}
#pragma mark -
#pragma mark Turn Undead Methods
#pragma mark
+(void)updateTurnUndeadForChar:(NSManagedObject *)obj{
	int chaMod=[self scoreToBonus:[obj valueForKey:@"charisma"]];
	//NSLog(@"chaMod=%d",chaMod);
	[obj setValue:[NSNumber numberWithInt:(3+chaMod+[[obj valueForKey:@"tuMiscBonus"] intValue])]
		   forKey:@"tuTotal"];
	[obj setValue:[NSNumber numberWithInt:(chaMod+[[obj valueForKey:@"tuCMiscBonus"] intValue])]
		   forKey:@"tuCtotal"];
}
+(BOOL)characterTurnsOrRebukesUndead:(NSManagedObject *)obj{
	int i;
	for(i=1;i<4;i++){
		NSManagedObject *characterClass=[obj valueForKey:[NSString stringWithFormat:@"characterClass%d",i]];
		if(characterClass!=nil){
			if([[characterClass valueForKey:@"turnsUndead"] boolValue]){
				return YES;
			}
		}
	}
	return NO;
}
+(int)levelOfTurningForCharacter:(NSManagedObject *)obj{
	int maxLevel=INT_MIN;
	int i;
	for(i=1;i<4;i++){
		NSManagedObject *characterClass=[obj valueForKey:[NSString stringWithFormat:@"characterClass%d",i]];
		if(characterClass!=nil){
			if([[characterClass valueForKey:@"turnsUndead"] boolValue]){
				int level;
				if([[characterClass valueForKey:@"turnsAsLevelMinusThree"] boolValue]){
					level=[[obj valueForKey:[NSString stringWithFormat:@"charClassLvl%d",i]] intValue]-3;
				}else{
					level=[[obj valueForKey:[NSString stringWithFormat:@"charClassLvl%d",i]] intValue];					
				}
				if(level>maxLevel){
					maxLevel=level;
				}
			}
		}
	}
	if(maxLevel<0){
		maxLevel=0;
	}
	return maxLevel;
}
@end
